package yf.platform.dao;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.jdbc.ScriptRunner;
import org.apache.ibatis.session.RowBounds;
import org.mybatis.spring.SqlSessionTemplate;
import org.yfsoft.comm.util.StringUtil;

public class BasicDao implements DaoSupport {

	private static String MAPPER_ID_EXECUTE = "execute";
	
	private static String MAPPER_ID_FIND = "find";
	
	private static String MAPPER_ID_TABLE = "table";
	
	private static String MAPPER_ID_DELETE = "delete";
	
	private static String MAPPER_ID_INSERT = "insert";
	
	private static String MAPPER_ID_QUERY = "query";
	
	private static String MAPPER_KEY_COLUMNS = "columns";
	
	private static String MAPPER_KEY_VALUES = "values";
	
	private static String MAPPER_ID_DESC_TABLE = "desc_table";
	
	private static String MAPPER_KEY_TABLE = "table_name";
	
	private static String MAPPER_KEY_CONDITION = "condition";
	
	private static String MAPPER_KEY_ORDER = "order";
	
	private static String MAPPER_KEY_FIELDS = "fields";
	
	private SqlSessionTemplate sqlSessionTemplate = null;
	
	@Override
	public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
		this.sqlSessionTemplate = sqlSessionTemplate;
	}
	

	@Override
	public void runScript(String path) throws IOException {
		Connection conn;
		try {
			conn = this.sqlSessionTemplate.getConfiguration().getEnvironment().getDataSource().getConnection();
		} catch (SQLException e) {
			throw new IOException(e);
		}
		ScriptRunner sr = new ScriptRunner(conn);
		InputStream is = BasicDao.class.getClassLoader().getResourceAsStream(path);
		InputStreamReader isr = new InputStreamReader(is, "UTF8"); 
		Reader reader = new BufferedReader(isr); 
		//Reader reader = Resources.getResourceAsReader(path);
		sr.runScript(reader);
	}

	

	@Override
	public <T> List<T> desc(String table) {
		Map<String,Object> e = new HashMap<String,Object>();
		e.put(MAPPER_KEY_TABLE, table);
		return this.sqlSessionTemplate.selectList(MAPPER_ID_DESC_TABLE, e);
	}

	

	@Override
	public <T> List<T> table() {
		
		return this.sqlSessionTemplate.selectList(MAPPER_ID_TABLE);
	}


	@Override
	public void beginTransaction() {
	}

	@Override
	public void commit() {
		this.sqlSessionTemplate.commit();
	}

	@Override
	public void rollback() {
		this.sqlSessionTemplate.rollback();
	}

	@Override
	public int execute(String sql) {
		return this.sqlSessionTemplate.insert(MAPPER_ID_EXECUTE, sql);
	}

	@Override
	public <T> int insert( T e,String id) {
		return this.sqlSessionTemplate.insert(id, e);
	}
	
	@Override
	public <T> int update(String id, T e) {
		return this.sqlSessionTemplate.update(id, e);

	}

	private String parseUpdateSql(Map<String,String> e,String table_name,String condition){
		String f,t,k;
		List<Map<String,Object>> list = this.desc(table_name);
		String sql = "update {0} set {1} where {2}";
		StringBuffer cols = new StringBuffer();
		for(Map<String,Object> o : list){
			k = o.get("Key").toString();//主键不能修改
			if("PRI".equals(k)) continue;
			f = o.get("Field").toString();//字段名称
			if(!e.containsKey(f)) continue;//未设置字段
			cols.append(f).append("=");
			t = o.get("Type").toString();//字段类型
			if(t.indexOf("int")<0){
				//字段未非整形
				cols.append("'").append(e.get(f)).append("'").append(",");
			}else{
				cols.append(e.get(f)).append(",");
			}
		}
		cols = cols.deleteCharAt(cols.length()-1);
		if(StringUtil.isNullOrEmpty(condition))
			condition = "1 = 1";
		sql = StringUtil.formatSql(sql,table_name, cols.toString(),condition);
		return sql;
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
	public int insert(String table_name,Map... es) {
		if(es == null){
			return -99;//错误,为传入要插入的值
		}
		int len = es.length;
		if(len<1){
			return -99;//错误,未传入要插入的值
		}
		List<Map<String,Object>> list = this.desc(table_name);
		String a,f,t;
		Map<String,String> cols_list = new HashMap<String,String>();
		Map<String,String> e = es[0];
		for(Map<String,Object> o : list){
			a = o.get("Extra").toString();//自增字段,过滤
			if("auto_increment".equals(a))	continue;
			f = o.get("Field").toString();//字段名称
			if(!e.containsKey(f)) continue;//未设置字段
			t = o.get("Type").toString();//字段类型
			cols_list.put(f,t);			
		}
		StringBuffer vals = new StringBuffer();
		for(int i = 0 ; i<len ; i++){
			e = es[i];
			vals.append("(");
			for(String c : cols_list.keySet()){
				if(cols_list.get(c).indexOf("int")<0){
					//字段未非整形
					vals.append("'").append(e.get(c)).append("'").append(",");
				}else{
					vals.append(e.get(c)).append(",");
				}
			}
			vals = vals.deleteCharAt(vals.length()-1);
			vals.append("),");
		}
		vals = vals.deleteCharAt(vals.length()-1);
		Map<String,Object> p = new HashMap<String,Object>();
		p.put(MAPPER_KEY_TABLE,table_name);
		p.put(MAPPER_KEY_COLUMNS, StringUtils.join(cols_list.keySet(), ","));
		p.put(MAPPER_KEY_VALUES, vals);
		int rows = this.sqlSessionTemplate.insert(MAPPER_ID_INSERT, p);
		if(rows<1){
			return rows;
		}else if(rows ==1){
			List<Map<String,Object>> ids = this.find("SELECT LAST_INSERT_ID()");
			Map<String,Object> id = ids.get(0);
			return Integer.parseInt(id.get("LAST_INSERT_ID()").toString());
		}else{
			return rows;
		}
	}
	

	@Override
	public int delete(String table, String condition) {
		Map<String,Object> e = new HashMap<String,Object>();
		e.put(MAPPER_KEY_TABLE,table);
		e.put(MAPPER_KEY_CONDITION, condition);
		return this.sqlSessionTemplate.delete(MAPPER_ID_DELETE, e);
	}


	@Override
	public int update(Map<String,String> e, String condition, String table_name) {
		String sql = parseUpdateSql(e,table_name,condition);
		return this.execute(sql);
	}


	
	@Override
	public <T> List<T> find(String sql) {
		return this.sqlSessionTemplate.selectList(MAPPER_ID_QUERY, sql);
	}


	@Override
	public <T> T findOne(String id, Object e) {
		T t = this.sqlSessionTemplate.selectOne(id, e);
		return t;
	}

	@Override
	public <T> T findOne(String table_name, String fields, String condition) {
		Map<String,Object> e = new HashMap<String,Object>();
		e.put(MAPPER_KEY_TABLE, table_name);
		e.put(MAPPER_KEY_FIELDS, StringUtil.isNullOrEmpty(fields)?"*":fields);
		e.put(MAPPER_KEY_CONDITION, StringUtil.isNullOrEmpty(condition)?"1 = 1":condition);
		return this.sqlSessionTemplate.selectOne(MAPPER_ID_FIND, e);
	}

	@Override
	public <T> List<T> find(String id, Object e) {
		return this.sqlSessionTemplate.selectList(id, e);
	}
	
	@Override
	public <T> List<T> find(String table_name, String fields, String condition,String order) {
		Map<String,Object> e = new HashMap<String,Object>();
		e.put(MAPPER_KEY_TABLE, table_name);
		e.put(MAPPER_KEY_FIELDS, StringUtil.isNullOrEmpty(fields)?"*":fields);
		e.put(MAPPER_KEY_CONDITION, StringUtil.isNullOrEmpty(condition)?"1 = 1":condition);
		e.put(MAPPER_KEY_ORDER, StringUtil.isNullOrEmpty(order)?" ":"order by ".concat(order));
		return this.sqlSessionTemplate.selectList(MAPPER_ID_FIND, e);
	}

	@Override
	public <T> List<T> findByPage(String id, Object e, int page, int max) {
		return this.sqlSessionTemplate.selectList(id, e, new RowBounds(page,max));
	}


	@Override
	public <T> List<T> findByPage(String table_name, String fields,
			String condition,String order, int page, int max) {
		Map<String,Object> e = new HashMap<String,Object>();
		e.put(MAPPER_KEY_TABLE, table_name);
		e.put(MAPPER_KEY_FIELDS, StringUtil.isNullOrEmpty(fields)?"*":fields);
		e.put(MAPPER_KEY_CONDITION, StringUtil.isNullOrEmpty(condition)?"1 = 1":condition);
		e.put(MAPPER_KEY_ORDER, StringUtil.isNullOrEmpty(order)?" ":"order by ".concat(order));
		return this.sqlSessionTemplate.selectList(MAPPER_ID_FIND, e,new RowBounds(page,max));
	}


	@Override
	public <T> List<T> injoin(String tables, String fields,String condition, String order) {
		Map<String,Object> e = new HashMap<String,Object>();
		e.put(MAPPER_KEY_TABLE, tables);
		e.put(MAPPER_KEY_FIELDS, StringUtil.isNullOrEmpty(fields)?"*":fields);
		e.put(MAPPER_KEY_CONDITION, StringUtil.isNullOrEmpty(condition)?"1 = 1":condition);
		e.put(MAPPER_KEY_ORDER, StringUtil.isNullOrEmpty(order)?" ":"order by ".concat(order));
		return this.sqlSessionTemplate.selectList(MAPPER_ID_FIND, e);
	}


	@Override
	public <T> List<T> injoin(String tables, String fields,String condition, String order, int max, int page) {
		Map<String,Object> e = new HashMap<String,Object>();
		e.put(MAPPER_KEY_TABLE, tables);
		e.put(MAPPER_KEY_FIELDS, StringUtil.isNullOrEmpty(fields)?"*":fields);
		e.put(MAPPER_KEY_CONDITION, StringUtil.isNullOrEmpty(condition)?"1 = 1":condition);
		e.put(MAPPER_KEY_ORDER, StringUtil.isNullOrEmpty(order)?" ":"order by ".concat(order));
		return this.sqlSessionTemplate.selectList(MAPPER_ID_FIND, e,new RowBounds(page,max));
	}

	
	
}
